@tool
class_name State
extends Node

@export var cooling_time:float = 0
@export var state_name:String
@export var display_name:String
# 采用懒处理模式，只有调用get_state_status()时才可能修改Closed -> Ready
var cur_state_status:GameEnum.StateStatus = GameEnum.StateStatus.Ready
var transitions:Array[Transition] = []
var transition_delay:Transition = null
var transition_delay_time = 0
var parent_state
var fsm:FSM
var enter_time:float
# 上一次退出的时间
var last_exit_time:float = -INF
# 切换状态
# st_state: 起始状态
# to_state: 目标状态
signal on_translate_state(st_state,to_state)

func state_init(fsm:FSM):
	self.fsm = fsm
	parent_state = get_parent()
	transitions.clear()
	for child in get_children():
		if child is Transition:
			transitions.append(child)

func on_enter(from_state:State):
	cur_state_status = GameEnum.StateStatus.Excuting
	enter_time = Time.get_ticks_msec()
func on_update(delta:float):
	if cur_state_status != GameEnum.StateStatus.Excuting:
		return
	if transition_delay != null:
		transition_delay_time -= delta
		if transition_delay_time <= 0:
			var to_state = transition_delay.resolve_target()
			on_translate_state.emit(self,to_state)
			return
	else:
		for transition:Transition in transitions:
			if transition.active and transition.evaluate_guard():
				if transition.delay_seconds > 0:
					transition_delay = transition
					transition_delay_time = transition.delay_seconds
					cur_state_status = GameEnum.StateStatus.Waiting
					return
				else:
					var to_state = transition.resolve_target()
					on_translate_state.emit(self,to_state)
func on_physics_update(delta:float):
	if cur_state_status != GameEnum.StateStatus.Excuting:
		return
func on_exit(to_state:State):
	if cur_state_status != GameEnum.StateStatus.Excuting and cur_state_status != GameEnum.StateStatus.Waiting:
		return
	cur_state_status = GameEnum.StateStatus.Closed
	transition_delay = null
	transition_delay_time = 0
	last_exit_time = Time.get_ticks_msec()
func get_state_status() -> GameEnum.StateStatus:
	# 下面主要是用于懒处理冷却时间问题，冷却结束返回Ready
	cur_state_status = GameEnum.StateStatus.Ready if cur_state_status == GameEnum.StateStatus.Closed and last_exit_time + cooling_time * 1000 <= Time.get_ticks_msec() else cur_state_status
	return cur_state_status
func translate_state(st_state:State,to_state:State,st_state_path:Array[State],to_state_path:Array[State]):
	pass
func _get_configuration_warnings() -> PackedStringArray:
	var result = []
	var parent = get_parent()
	var found = false
	while is_instance_valid(parent):
		if parent is FSM:
			found = true
			break
		parent = parent.get_parent()
	if not found:
		result.append("State必须是FSM的子孙节点")
	return result
